package com.tinyengine.it.controller.vue;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.tinyengine.it.common.base.Result;
import com.tinyengine.it.common.utils.GenDir;
import com.tinyengine.it.model.entity.TApp;
import com.tinyengine.it.model.entity.TPage;
import com.tinyengine.it.model.vo.vue.MenuVo;
import com.tinyengine.it.model.vo.vue.Route;
import com.tinyengine.it.service.engine.extend.TAppService;
import com.tinyengine.it.service.engine.extend.TPageService;
import com.tinyengine.it.service.generator.GitPushService;
import com.tinyengine.it.service.vue.VueGenerationService;
import com.tinyengine.it.tool.ZipUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.zip.ZipOutputStream;

@Tag(name = "VUE功能模块")
@Slf4j
@RestController
@RequestMapping("/vue")
@RequiredArgsConstructor
public class VueController {

    private final TPageService tPageService;
    private final VueGenerationService vueGenerationService;
    private final TAppService tAppService;
    private final GitPushService gitPushService;

    @Operation(summary = "下载单个 Vue 文件;以流的方式传输给客户端", method = "GET", tags = {"VUE功能模块"})
    @GetMapping("/generation-vue")
    public ResponseEntity<InputStreamResource> generationInputStream(@RequestParam Integer appId, @RequestParam Integer id) {
        TPage page = tPageService.getOne(new LambdaQueryWrapper<TPage>().eq(TPage::getAppId, appId).eq(TPage::getId, id));
        String vueContent = tPageService.generationSfcContent(page.getSfcContent());

        // 将 Vue 内容转换为 InputStream
        InputStream inputStream = new ByteArrayInputStream(vueContent.getBytes(StandardCharsets.UTF_8));

        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + page.getName() + ".vue");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        // 返回流式响应
        return ResponseEntity.ok()
                .headers(headers)
                .body(new InputStreamResource(inputStream));
    }

    @Operation(summary = "buildVue工程,并上传至Git", method = "GET", tags = {"VUE功能模块"})
    @GetMapping("/generation-project")
    public Result generationProject(@RequestParam Integer appId) throws IOException, InterruptedException {

        vueGenerationService.initProject(appId);
        vueGenerationService.viewsFileGenerator(appId);

        //路由暂不生产
        //vueGenerationService.routerConfigGenerator();

        try {
            TApp tApp = tAppService.getById(appId);
            if (StrUtil.isBlank(tApp.getGitRepoVueUrl())) {
                return Result.success("Git仓库地址未配置");
            }
            String message = gitPushService.syncAndPush(
                    tApp.getGitRepoVueUrl(), // GIT_REPO_URL
                    String.format(GenDir.optTargetGitVueDirLinux, appId), // LOCAL_GIT_DIR
                    GenDir.getVueOptTargetPathBasedOnOS(appId) // BLADEX_SOURCE_DIR
            );
            return Result.success(message);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return Result.success();
    }

    @Operation(summary = "下载zip工程包,并build工程", description = "返回 ZIP 文件")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功",
                    content = @Content(mediaType = "application/zip",
                            schema = @Schema(type = "string", format = "binary"))),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/download/project")
    public ResponseEntity<ByteArrayResource> downloadZip(@RequestParam Integer appId) throws IOException, InterruptedException {
        generationProject(appId);
        // 打包路径
        String optVueTargetPathBasedOnOS = GenDir.getVueOptTargetPathBasedOnOS(appId);
        Path sourceFolder = Paths.get(optVueTargetPathBasedOnOS);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (ZipOutputStream zipOut = new ZipOutputStream(byteArrayOutputStream)) {
            // 递归压缩文件夹及其内容
            ZipUtils.zipDirectory(sourceFolder, sourceFolder.getFileName().toString(), zipOut);
        }
        // 将压缩文件作为下载响应返回
        ByteArrayResource resource = new ByteArrayResource(byteArrayOutputStream.toByteArray());

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + sourceFolder.getFileName() + ".zip")
                .contentType(MediaType.parseMediaType("application/zip"))
                .body(resource);
    }

    @Operation(summary = "获取菜单SQL脚本文件", method = "GET", tags = {"VUE功能模块"})
    @GetMapping("/getInsertMenuSql")
    public ResponseEntity<ByteArrayResource> getInsertMenuSql(@RequestParam Integer appId) {

        List<TPage> pages = tPageService.list(new LambdaQueryWrapper<TPage>().eq(TPage::getAppId, appId));

        List<Route> routes = BeanUtil.copyToList(pages, Route.class);

        routes.parallelStream().forEach(route -> route.setMenuId(DefaultIdentifierGenerator.getInstance().nextId(MenuVo.class)));

        List<Route> routeTree = vueGenerationService.buildRouteTree(routes);

        List<MenuVo> menuVos = vueGenerationService.printRouteList(routeTree);

        // 生成 SQL 内容
        StringBuilder sqlBuilder = new StringBuilder();
        for (MenuVo menu : menuVos) {
            sqlBuilder.append(menu.generateInsertSQL()).append("\n");
        }

        // 转换为 byte 数组资源
        byte[] sqlBytes = sqlBuilder.toString().getBytes(StandardCharsets.UTF_8);
        ByteArrayResource resource = new ByteArrayResource(sqlBytes);

        // 响应头设置为下载
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=blade_menu.sql")
                .contentLength(sqlBytes.length)
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(resource);
    }
}
